import WhistleBridge from '..';
import { WhistleBridgePlugin } from '../type';
import { evalJs } from '../utils';
import BridgePlugin from './bridge';

export default class MessagePlugin implements WhistleBridgePlugin {
  public name: string = 'messagePlugin';
  public root: WhistleBridge;
  public hasInitd: boolean = false;
  public source: EventSource = null;

  private bridgePlugin: BridgePlugin = null;
  private retryTimes: number = 0;

  static instance: MessagePlugin = null;

  public onInit(params: any) {
    this.root = params.root as WhistleBridge;
    MessagePlugin.instance = this;
  }

  public onBridged({ bridgePlugin }: any) {
    if (this.hasInitd) {
      return;
    }

    this.hasInitd = true;
    this.bridgePlugin = bridgePlugin;
    const { config } = this.root;
    let source: EventSource;

    try {
      source = new EventSource(`${config.baseUrl}/sse?name=${config.name}`);
    } catch (error) {
      console.error(error);
    }

    source.onopen = () => {
      console.log('%c message plugin open ', 'background: #222; color: #EE6A55');
      this.root.setMessagePlugin(this);
    };

    source.onerror = event => {
      if (source.readyState === EventSource.CLOSED) {
        source.close();
        return;
      }
      if (source.readyState === EventSource.CONNECTING) {
        this.retryTimes++;
        if (this.retryTimes > 10) {
          this.source.close();
          console.log('abort retring')
        }
      }
      console.error(event);
    };

    source.onmessage = originData => {
      const payload = JSON.parse(originData.data);

      this.handleMesssageReceived(payload);
    };

    this.source = source;
  }

  private handleMesssageReceived(payload: Record<string, any>) {
    switch (payload.type) {
      case 'exec':
        const execuableCode = payload.data;
        const result = evalJs(execuableCode);
        console.log(`%c exec ${execuableCode} `, 'background: #fff; color: #888');
        console.log(`exec result ${result}`);
        break;

      case 'bridge':
        const receiveMethod = this.bridgePlugin.receiveMethod || (() => {});
        receiveMethod(payload.data);

      case 'close':
        this.source.close();
        console.log('%c message plugin closed ', 'background: #333; color: #EE6022');
      default:
        break;
    }
  }
}
